package com.niodata.dp.core.resource;

import com.niodata.dp.core.resource.impl.DashBoardResource;
import com.niodata.dp.core.resource.impl.DbResource;
import com.niodata.dp.core.resource.impl.DsResource;
import com.niodata.dp.core.resource.impl.FileResource;
import com.niodata.dp.core.resource.impl.GroupResource;
import com.niodata.dp.core.resource.impl.JobResource;
import com.niodata.dp.core.resource.impl.ObjectResource;
import com.niodata.dp.core.resource.impl.PluginResource;
import com.niodata.dp.core.resource.impl.TableResource;
import com.niodata.dp.core.resource.impl.TaskConfResource;
import com.niodata.dp.core.resource.impl.UserResource;
import com.niodata.dp.core.resource.impl.VisualResource;
import java.util.ArrayList;
import java.util.List;

public abstract class ResourceType {

  public static final FileType File;
  public static final ObjectType Object;
  public static final VisualType Visual;
  public static final PluginType Plugin;
  public static final JobType Job;
  public static final UserType User;
  public static final GroupType Group;
  public static final DbType Db;
  public static final TableType Table;
  public static final DashBoardType DashBoard;
  public static final TaskConfType TaskConf;
  public static final MetricsMonitorType MetricMonitor;
  public static final DsType Ds;
  public static final NoOpType NoOp;
  public static final NoteBookResType NoteBook;
  public static final DiResType DataEntityInterface;
  private static final List<ResourceType> typeList = new ArrayList<>();

  static {
    File = new FileType();
    Object = new ObjectType();
    Visual = new VisualType();
    Plugin = new PluginType();
    Job = new JobType();
    User = new UserType();
    Group = new GroupType();
    Db = new ResourceType.DbType();
    Table = new ResourceType.TableType();
    DashBoard = new DashBoardType();
    TaskConf = new TaskConfType();
    MetricMonitor = new MetricsMonitorType();
    Ds = new DsType();
    NoOp = new NoOpType();
    NoteBook = new NoteBookResType();
    DataEntityInterface = new DiResType();

    typeList.add(File);
    typeList.add(Plugin);
    typeList.add(Object);
    typeList.add(Group);
    typeList.add(User);
    typeList.add(Visual);
    typeList.add(Db);
    typeList.add(Table);
    typeList.add(DashBoard);
    typeList.add(TaskConf);
    typeList.add(MetricMonitor);
    typeList.add(Ds);
    typeList.add(NoOp);
    typeList.add(NoteBook);
    typeList.add(DataEntityInterface);
  }

  private final String protocol;

  private ResourceType(String protocol) {
    this.protocol = protocol;
  }

  public static ResourceType getResourceTypeByName(String typeName) {
    for (ResourceType type : typeList) {
      if (type.getTypeName().equals(typeName)) {
        return type;
      }
    }
    return null;
  }

  /**
   * 返回操作继承列表，权限从小到大排列.
   *
   * @return operations
   */
  public abstract String[] getHierarchyOperations();

  /**
   * 返回指定操作的继承操作列表，权限从小到大排列.
   *
   * @param operation operation
   * @return HierarchyParentOperations
   */
  public String[] getHierarchyParentOperations(String operation) {
    int index = 0;
    for (int i = 0; i < this.getHierarchyOperations().length; i++) {
      if (this.getHierarchyOperations()[i].equals(operation)) {
        index = i;
      }
    }
    if (index < this.getHierarchyOperations().length - 1) {
      String[] ops = new String[getHierarchyOperations().length - index - 1];
      System.arraycopy(this.getHierarchyOperations(), index + 1, ops, 0, ops.length);
      return ops;
    }

    return new String[]{};
  }

  public String getTypeName() {
    return this.protocol;
  }

  public abstract Resource createResource(String identifier);


  public String protocol() {
    return protocol;
  }

  public String formatPrefix() {
    return protocol + "://";
  }

  public static class FileType extends ResourceType {

    public static final String ReadWrite = "ReadWrite";
    public static final String Upload = "Upload";
    public static final String Read = "Read";
    public static final String List = "List";
    public static final String DownLoad = "Download";
    public static final String Delete = "Delete";

    FileType() {
      super("FILE");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Read, List, DownLoad, ReadWrite, Upload, Delete};
    }

    public Resource createResource(String identifier) {
      return new FileResource(identifier);
    }

  }

  public static class TaskConfType extends ResourceType {

    public static final String Create = "Create";
    public static final String Update = "Update";
    public static final String Delete = "Delete";

    public TaskConfType() {
      super("TASKCONF");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Create, Delete};
    }

    @Override
    public Resource createResource(String identifier) {
      return new TaskConfResource(identifier);
    }
  }

  public static class DashBoardType extends ResourceType {

    public static final String View = "View";
    public static final String Update = "Update";
    public static final String Delete = "Delete";

    public DashBoardType() {
      super("DASHBOARD");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{View, Delete};
    }

    @Override
    public Resource createResource(String identifier) {
      return new DashBoardResource(identifier);
    }
  }

  public static class ObjectType extends ResourceType {

    public static final String Upload = "Upload";
    public static final String Download = "Download";
    public static final String Delete = "Delete";
    public static final String Create = "Create";

    ObjectType() {
      super("BUCKET");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Upload, Download, Delete, Create};
    }

    public Resource createResource(String identifier) {
      return new ObjectResource(identifier);
    }

  }


  public static class VisualType extends ResourceType {

    public static final String Create = "Create";
    public static final String Download = "Download";
    public static final String Delete = "Delete";

    VisualType() {
      super("VISUAL");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Create, Download, Delete};
    }

    public Resource createResource(String identifier) {
      return new VisualResource(identifier);
    }


  }

  public static class PluginType extends ResourceType {

    public static final String Upload = "Upload";
    public static final String Delete = "Delete";

    PluginType() {
      super("PLUGIN");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Upload, Delete};
    }

    public Resource createResource(String identifier) {
      return new PluginResource(identifier);
    }


  }

  public static class JobType extends ResourceType {

    public static final String Schedule = "Schedule";
    public static final String Pause = "Pause";
    public static final String Resume = "Resume";
    public static final String Remove = "Remove";
    public static final String Update = "Update";

    JobType() {
      super("TASK");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Schedule, Pause, Resume, Update, Remove};
    }

    public Resource createResource(String identifier) {
      return new JobResource(identifier);
    }


  }

  public static class UserType extends ResourceType {

    public static final String Create = "Create";
    public static final String Delete = "Delete";

    UserType() {
      super("USER");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Create, Delete};
    }

    public Resource createResource(String identifier) {
      return new UserResource(identifier);
    }


  }

  public static class GroupType extends ResourceType {

    public static final String Create = "Create";
    public static final String Delete = "Delete";
    public static final String AddUser = "AddUser";
    public static final String RemoveUser = "RemoveUser";

    GroupType() {
      super("GROUP");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Create, Delete, AddUser, RemoveUser};
    }

    public Resource createResource(String identifier) {
      return new GroupResource(identifier);
    }


  }

  public static class DsType extends ResourceType {

    public static final String Select = "select";
    public static final String CreateDb = "createDb";


    public DsType() {
      super("DS");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Select};
    }
    /*
    public String[] getHierarchyOperations() {
      return new String[]{Select, CreateDb};
    }
    */

    @Override
    public Resource createResource(String identifier) {
      return new DsResource(identifier);
    }
  }

  public static class DbType extends ResourceType {

    public static final String Create = "createTable";
    public static final String Select = "select";
    public static final String Update = "update";
    public static final String DropTable = "dropTable";
    public static final String DropDb = "dropDb";

    public DbType() {
      super("DB");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Select};
    }
    /*
    public String[] getHierarchyOperations() {
      return new String[]{Select, Update, Create, DropTable, DropDb};
    }
    */

    @Override
    public Resource createResource(String identifier) {
      return new DbResource(identifier);
    }
  }

  public static class SystemType extends ResourceType {

    private SystemType(String protocol) {
      super(protocol);
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{};
    }

    @Override
    public Resource createResource(String identifier) {
      return null;
    }

  }

  public static class TableType extends ResourceType {

    public static final String Create = "create";
    public static final String Drop = "drop";
    public static final String Delete = "delete";
    public static final String Select = "select";

    public TableType() {
      super("TABLE");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Select};
    }
    /*
    public String[] getHierarchyOperations() {
      return new String[]{Select, Create, Delete, Drop};
    }
    */

    @Override
    public Resource createResource(String identifier) {
      return new TableResource(this, identifier);
    }

    public Resource createResource(String dsName, String dbName, String tableName) {
      TableResource resource = new TableResource(dsName, dbName, tableName);
      return resource;
    }
  }

  public static class MetricsMonitorType extends ResourceType {

    public static final String Monitor = "Monitor";

    public MetricsMonitorType() {
      super("MetricsMonitor");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{Monitor};
    }

    @Override
    public Resource createResource(String identifier) {
      return null;
    }
  }

  public static class NoOpType extends ResourceType {

    public NoOpType() {
      super("NoOp");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{};
    }

    @Override
    public Resource createResource(String identifier) {
      return null;
    }
  }

  public static class NoteBookResType extends ResourceType {

    public NoteBookResType() {
      super("NoteBook");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{};
    }

    @Override
    public Resource createResource(String identifier) {
      return null;
    }
  }

  public static class DiResType extends ResourceType {

    public DiResType() {
      super("DiRes");
    }

    @Override
    public String[] getHierarchyOperations() {
      return new String[]{"Query"};
    }

    @Override
    public Resource createResource(String identifier) {
      return null;
    }
  }
}
